﻿;;
;; Trackpoint.ahk (AutoHotkey v2.0 版本)
;; 原作者: Chiyuan Zhang <pluskid@gmail.com>
;; v2.0 适配版本
;;
;; 功能: 让Thinkpad Trackpoint的中键既能单击也能滚动
;; 短按中键：普通中键点击
;; 按住中键并移动：滚动页面
;;

#NoTrayIcon ; 可选，隐藏托盘图标

; 配置参数
; 毫秒阈值，按住中键超过此时间则开始检测滚动
tp_StartScrollTThreshold := 200
; 像素阈值，X/Y方向移动超过此值才开始滚动
tp_StartScrollXThreshold := 2
tp_StartScrollYThreshold := 2
; 检查滚动的间隔时间（毫秒），值越小滚动越平滑
tp_ScrollCheckInterval := 10
; 滚动速度系数，值越大滚动越敏感
tp_ScrollSpeedFactorX := 0.05
tp_ScrollSpeedFactorY := 0.05
; 鼠标速度平滑因子
tp_SmoothFactor := 0.7

; 触发滚动的按键（中键）
tp_TriggerKey := "MButton"

; 初始化全局变量
tp_Scroll := false
tp_AnchorX := 0
tp_AnchorY := 0
tp_LastVelocityX := 0
tp_LastVelocityY := 0

; 设置热键
Hotkey tp_TriggerKey, tp_TriggerKeyDown
Hotkey tp_TriggerKey " Up", tp_TriggerKeyUp
return

; 中键按下事件
tp_TriggerKeyDown(thisHotkey) {
    global tp_Scroll := false
    global tp_AnchorX, tp_AnchorY
    global tp_LastVelocityX := 0
    global tp_LastVelocityY := 0
    MouseGetPos(&tp_AnchorX, &tp_AnchorY)
    SetTimer tp_CheckForScrollEventAndExecute, tp_StartScrollTThreshold
}

; 中键释放事件
tp_TriggerKeyUp(thisHotkey) {
    SetTimer tp_CheckForScrollEventAndExecute, 0
    ; 如果没有触发滚动，则发送中键点击
    if (!tp_Scroll) {
        Click "Middle"
    }
}

; 检查并执行滚动
tp_CheckForScrollEventAndExecute() {
    global tp_Scroll, tp_AnchorX, tp_AnchorY
    global tp_ScrollSpeedFactorX, tp_ScrollSpeedFactorY
    global tp_LastVelocityX, tp_LastVelocityY, tp_SmoothFactor
    
    ; 首次触发滚动时
    if (!tp_Scroll) {
        tp_Scroll := true
        SetTimer tp_CheckForScrollEventAndExecute, tp_ScrollCheckInterval
    }
    
    MouseGetPos(&tp_NewX, &tp_NewY)
    tp_DistanceX := tp_NewX - tp_AnchorX
    tp_DistanceY := tp_NewY - tp_AnchorY
    
    ; 应用平滑处理
    tp_CurrentVelocityX := tp_DistanceX * tp_ScrollSpeedFactorX
    tp_CurrentVelocityY := tp_DistanceY * tp_ScrollSpeedFactorY
    
    ; 使用指数平滑来避免突变
    tp_CurrentVelocityX := (tp_CurrentVelocityX * (1 - tp_SmoothFactor)) + (tp_LastVelocityX * tp_SmoothFactor)
    tp_CurrentVelocityY := (tp_CurrentVelocityY * (1 - tp_SmoothFactor)) + (tp_LastVelocityY * tp_SmoothFactor)
    
    ; 更新上一次速度
    tp_LastVelocityX := tp_CurrentVelocityX
    tp_LastVelocityY := tp_CurrentVelocityY
    
    ; 累积滚动量，使用小数部分以支持小范围移动
    static tp_AccumX := 0, tp_AccumY := 0
    tp_AccumX += tp_CurrentVelocityX
    tp_AccumY += tp_CurrentVelocityY
    
    ; Y轴滚动检测 - 使用累积量
    if (Abs(tp_AccumY) >= 1) {
        ; 计算需要滚动的次数和方向
        tp_ScrollY := Floor(Abs(tp_AccumY))
        if (tp_AccumY > 0) {
            SendInput "{WheelDown " tp_ScrollY "}"
            tp_AccumY -= tp_ScrollY
        } else {
            SendInput "{WheelUp " tp_ScrollY "}"
            tp_AccumY += tp_ScrollY
        }
    }
    
    ; X轴滚动检测 - 使用累积量
    if (Abs(tp_AccumX) >= 1) {
        tp_ScrollX := Floor(Abs(tp_AccumX))
        try {
            FocusedControl := ControlGetFocus("A")
            if (tp_AccumX > 0) {
                Loop tp_ScrollX {
                    PostMessage(0x114, 1, 0, FocusedControl, "A") ; 0x114 = WM_HSCROLL, 1 = SB_LINERIGHT
                }
                tp_AccumX -= tp_ScrollX
            } else {
                Loop tp_ScrollX {
                    PostMessage(0x114, 0, 0, FocusedControl, "A") ; 0x114 = WM_HSCROLL, 0 = SB_LINELEFT
                }
                tp_AccumX += tp_ScrollX
            }
        }
    }
    
    ; 将鼠标位置重置回原始位置
    if (tp_DistanceX != 0 || tp_DistanceY != 0) {
        BlockInput "MouseMove"
        MouseMove tp_AnchorX, tp_AnchorY, 0
        BlockInput "MouseMoveOff"
    }
}

